#include "testApp.h"

// ofSerialSampler by Keith Simmons
// ksimmons@gmail.com
// http://ksimmulator.com/
// a quick way to parse sensor input from an arduino


//--------------------------------------------------------------
void testApp::setup(){
    ofSetWindowTitle("ofSerialSampler");
	ofSetVerticalSync(true);
	ofBackground(255,255,255);
	ofSetLogLevel(OF_LOG_NOTICE);

	//-----------------------------------
	font.loadFont("DIN.otf", 64);

	serial.listDevices();
	vector <ofSerialDeviceInfo> deviceList = serial.getDeviceList();


	graphX = ofGetWindowWidth()-320-1; // -1 is for border
    graphY = ofGetWindowHeight()-240-1;

	//----------------------------------- note:
	// < this should be set
	// to whatever com port
	// your serial device is
	// connected to.
	// (ie, COM4 on a pc, /dev/tty.... on linux, /dev/tty... on a mac)
	// arduino users check in arduino app....

	serial.setup(0, 9600); //open the first device
	sampleRate = 50; // 1000 millis

	//serial.setup("COM4");  						  // windows example
	//serial.setup("/dev/tty.usbserial-A4001JEC",9600); // mac osx example
	//serial.setup("/dev/ttyUSB0", 9600);			  //linux example

    int maxMessageLength = 4;
    // we want to read (1 + max length) * 2 bytes
    bytesRequired = (1 + maxMessageLength) * 2;
    bytes = new unsigned char[bytesRequired];
}

void testApp::getValue(){
    bytesRemaining = bytesRequired;

    // discard input until we find a new line
    if ( serial.available() > 0 )
    {
        while (bytes[0] != '\n'){
            int result = serial.readBytes( &bytes[0], 1 );

            // check for error code
            if ( result == OF_SERIAL_ERROR )
            {
              // something bad happened
              ofLog( OF_LOG_ERROR, "unrecoverable error reading from serial" );

              // bail out
              break;
            }
        }
    }

    // now start reading from serial port
    bytesRead = 0;
    bytes[0] = 'K';

    // loop until we've read everything
    while ( bytesRemaining > 0 && bytes[bytesRead] != '\n' )
    {
      // check for data
      if ( serial.available() > 0 )
      {
        // try to read - note offset into the bytes[] array, this is so
        // that we don't overwrite the bytes we already have
        int bytesArrayOffset = bytesRequired - bytesRemaining;
        int result = serial.readBytes( &bytes[bytesArrayOffset],
          bytesRemaining );

        // check for error code
        if ( result == OF_SERIAL_ERROR )
        {
          // something bad happened
          ofLog( OF_LOG_ERROR, "unrecoverable error reading from serial" );

          // bail out
          break;
        }

        else if ( result == OF_SERIAL_NO_DATA )
        {
          // nothing was read, try again
        }

        else
        {
          // we read some data!
          bytesRemaining -= result;
          bytesRead+=result;

        }
      }

    }

    //terminate string
    for (int i = bytesRead; i>0; i--)
        if (bytes[i] == '\n')
            bytes[i] = '\0';

    //printf("bytes read are %d\n", bytesRead);
    //printf("mybytes are %s\n", (char*)bytes);

    renderGraph();
}

//--------------------------------------------------------------
void testApp::renderGraph(){
    // begin keith's graph code
        int barWidth = 1;

        ofDisableAlphaBlending();
        ofSetColor(255,255,255);

        ofSetColor(255);

        // clear bar on rightmost side of graph
        ofRect(graphX+(320), graphY, barWidth, 240);

        int val = atoi((char*)bytes);
        int valMapped = ofMap( val, 0, 1023, 0, 240 );

        // draw bar
        ofSetColor(255,0,0);
        ofRect(graphX+(320), graphY+(240-valMapped), barWidth, valMapped);

        // y axis tick marks
        for (int i = 0; i<10; i++){
            ofSetColor(200);
            ofRect(graphX+320, graphY+(i*240/10), 1, 1);
        }

        // grab screen buffer
        trackingGraph.grabScreen(graphX+barWidth, graphY, 320, 240);
    // end keith's graph code
}

//--------------------------------------------------------------
void testApp::update(){
    currentTimeMillis = ofGetElapsedTimeMillis();

    if (currentTimeMillis - lastTimeMillis > sampleRate) {
        if (serial.available() >= bytesRequired){ // is buffer full enough?
            getValue();
            lastTimeMillis = currentTimeMillis;
        }
    } else { // not time to sample yet, throw away data
        serial.flush();
    }
}

//--------------------------------------------------------------
void testApp::draw(){
    ofSetColor(255);
    ofDrawBitmapString("FPS: " + ofToString(ofGetFrameRate()), 20, ofGetWindowHeight()-20);

    int val = atoi((char*)bytes);

    // set background color based on val
    ofBackground( ofMap( val, 0, 1023, 0, 255 ), 0, 0 );

    // show the value read from serial (bytes)
	font.drawString(ofToString(bytes)+"/1023", 50,100);

    // draw our rotating sphere
    ofPushMatrix();
        ofSetColor(255);
        ofNoFill();
        ofTranslate(ofGetWindowWidth()/2,ofGetWindowHeight()/2);
        ofRotateY((ofGetElapsedTimeMillis()%36000)/100.0f);
        ofSphere(100.0f+(val/1023.0f)*300.0f);
    ofPopMatrix();

    // render graph on top of everything ever
    glDisable(GL_DEPTH);
        // black border
        ofSetColor(0);
        ofFill();
        ofRect(graphX-1, graphY-1, 320+2, 240+2 );

        // white background
        ofSetColor(255);
        ofRect(graphX, graphY, 320, 240);

        // finally, draw the actual graph
        ofSetColor(255);
        trackingGraph.draw(graphX, graphY, 320, 240);
    glEnable(GL_DEPTH);
}

//--------------------------------------------------------------
void testApp::keyPressed  (int key){

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){
    graphX = ofGetWindowWidth()-320-1; // -1 is for border
    graphY = ofGetWindowHeight()-240-1;
    trackingGraph.clear();
}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){

}

